package zelix.hack.hacks;

import net.minecraft.network.play.client.CPacketPlayer;
import net.minecraft.potion.Potion;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import zelix.hack.Hack;
import zelix.hack.HackCategory;
import zelix.utils.BlockUtils;
import zelix.utils.system.Mapping;
import zelix.value.Mode;
import zelix.value.ModeValue;
import zelix.utils.Wrapper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockIce;
import net.minecraft.block.BlockPackedIce;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.client.event.InputUpdateEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
import zelix.utils.MoveUtils;
import zelix.utils.PlayerControllerUtils;
import zelix.utils.TimerUtils;
import zelix.utils.Utils;

import java.lang.reflect.Field;

import static zelix.utils.MoveUtils.strafe;

public class Speed extends Hack {
	public ModeValue mode;

	public boolean shouldslow = false;
	double count = 0;
	int jumps;
	private float air, ground, aacSlow;
	public static TimerUtils timer = new TimerUtils();
	boolean collided = false, lessSlow;
	int spoofSlot = 0;
	double less, stair;

    Number ticks = 1.05f;
    private int offGroundTicks;

	private double speed, speedvalue;
	private double lastDist;
	public static int stage, aacCount;

	TimerUtils aac = new TimerUtils();
	TimerUtils lastFall = new TimerUtils();
	TimerUtils lastCheck = new TimerUtils();
  public static Minecraft mc = Wrapper.INSTANCE.mc();

	public Speed() {
		super("Speed", HackCategory.MOVEMENT);
		this.mode = new ModeValue("Mode", new Mode("Basic", false), new Mode("OldHypixel", false),
				new Mode("HYT", false),new Mode("AAC4", true),new Mode("AAC", false) , new Mode("VulcanLowHop" , false));

		this.addValue(mode);
	}
    @Override
    public void onDisable() {
	    //TimerUtils.settimer(1);
        setTickLength(50);
        super.onDisable();
    }

    @Override
    public void onEnable() {
        offGroundTicks = 0;
    }

	@Override
	public String getDescription() {
		return "You move faster.";
	}

	@Override
	public void onInputUpdate(InputUpdateEvent event) {
		Utils.nullCheck();
		if(!mode.getMode("HYT").isToggled()) {
			return;
		}
		if (MoveUtils.isMoving() && mc.player.onGround) {
            setTickLength(50 / ticks.floatValue());
            mc.player.motionY = 0.2;
			mc.player.jump();
            MoveUtils.strafe(0.3);
		}else {
            MoveUtils.strafe();
        }

		super.onInputUpdate(event);
	}



	@Override
	public void onClientTick(ClientTickEvent event) {
		if (mode.getMode("Basic").isToggled()) {
			boolean boost = Math
					.abs(Wrapper.INSTANCE.player().rotationYawHead - Wrapper.INSTANCE.player().rotationYaw) < 90;

			if (Wrapper.INSTANCE.player().moveForward > 0 && Wrapper.INSTANCE.player().hurtTime < 5) {
				if (Wrapper.INSTANCE.player().onGround) {
//            Wrapper.INSTANCE.player().jump();
					Wrapper.INSTANCE.player().motionY = 0.405;
					float f = Utils.getDirection();
					Wrapper.INSTANCE.player().motionX -= (double) (MathHelper.sin(f) * 0.2F);
					Wrapper.INSTANCE.player().motionZ += (double) (MathHelper.cos(f) * 0.2F);
				} else {
					double currentSpeed = Math
							.sqrt(Wrapper.INSTANCE.player().motionX * Wrapper.INSTANCE.player().motionX
									+ Wrapper.INSTANCE.player().motionZ * Wrapper.INSTANCE.player().motionZ);
					double speed = boost ? 1.0064 : 1.001;

					double direction = Utils.getDirection();

					Wrapper.INSTANCE.player().motionX = -Math.sin(direction) * speed * currentSpeed;
					Wrapper.INSTANCE.player().motionZ = Math.cos(direction) * speed * currentSpeed;
				}
			}
		} else if (mode.getMode("OldHypixel").isToggled()) {

			if (Wrapper.INSTANCE.player().collidedHorizontally) {
				collided = true;
			}

			if (collided) {
				// setTickLength(50);
				stage = -1;
			}

			if (stair > 0) {
				stair -= 0.25;
			}

			less -= less > 1 ? 0.12 : 0.11;

			if (less < 0) {
				less = 0;
			}

			if (!BlockUtils.isInLiquid() && MoveUtils.isOnGround(0.01) && (PlayerControllerUtils.isMoving2())) {
				collided = Wrapper.INSTANCE.player().collidedHorizontally;

				if (stage >= 0 || collided) {
					stage = 0;
					double motY = 0.407 + MoveUtils.getJumpEffect() * 0.1;

					if (stair == 0) {
						Wrapper.INSTANCE.player().jump();

						Wrapper.INSTANCE.player().motionY = motY;
					} else {
					}

					less++;

					if (less > 1 && !lessSlow) {
						lessSlow = true;
					} else {
						lessSlow = false;
					}

					if (less > 1.12) {
						less = 1.12;
					}
				}
			}

			speed = getHypixelSpeed(stage) + 0.0331;
			speed *= 0.91;

			if (stair > 0) {
				speed *= 0.7 - MoveUtils.getSpeedEffect() * 0.1;
			}

			if (stage < 0) {
				speed = MoveUtils.defaultSpeed();
			}

			if (lessSlow) {
				speed *= 0.95;
			}

			if (BlockUtils.isInLiquid()) {
				speed = 0.55;
			}

			if ((Wrapper.INSTANCE.player().moveForward != 0.0f || Wrapper.INSTANCE.player().moveStrafing != 0.0f)) {
				setMotion(speed);
				++stage;
			}
			
			
		}else if(mode.getMode("AAC4").isToggled()) {
		    Minecraft mc = Minecraft.getMinecraft();
            if(Wrapper.INSTANCE.mc().player.moveForward > 0) {
                if(Wrapper.INSTANCE.mc().player.onGround) {
                    Wrapper.INSTANCE.mc().player.jump();
                 //   TimerUtils.settimer(1.6105F);
                    this.setMotion(1.61);
                    Wrapper.INSTANCE.mc().player.motionX *= 1.0708;
                    Wrapper.INSTANCE.mc().player.motionZ *= 1.0708;
                }else if(Wrapper.INSTANCE.mc().player.fallDistance > 0 && Wrapper.INSTANCE.mc().player.fallDistance < 1){
                    this.setMotion(0.6);
                  //  TimerUtils.settimer(0.6F);
                }
            }
        }else if(mode.getMode("AAC").isToggled()) {
			
			
			 if (Wrapper.INSTANCE.player().fallDistance > 1.2)
             {
                 lastFall.reset();
             }

             if (!BlockUtils.isInLiquid() &&Wrapper.INSTANCE.player().collidedVertically && MoveUtils.isOnGround(0.01) && (Wrapper.INSTANCE.player().moveForward != 0.0f || Wrapper.INSTANCE.player().moveStrafing != 0.0f))
             {
                 stage = 0;
                 Wrapper.INSTANCE.player().jump();

                 Wrapper.INSTANCE.player().motionY=0.4199 + MoveUtils.getJumpEffect();
                 if (aacCount < 4)
                 {
                     aacCount++;
                 }
             }

             speed = getAACSpeed(stage, aacCount);

             if ((Wrapper.INSTANCE.player().moveForward != 0.0f || Wrapper.INSTANCE.player().moveStrafing != 0.0f))
             {
                 if (BlockUtils.isInLiquid())
                 {
                     speed = 0.075;
                 }

                 setMotion(speed);
             }

             if (Wrapper.INSTANCE.player().moveForward != 0.0f || Wrapper.INSTANCE.player().moveStrafing != 0.0f)
             {
                 ++stage;
             }
		}

        super.onClientTick(event);
	}





	private double getHypixelSpeed(int stage) {
		double value = MoveUtils.defaultSpeed() + (0.028 * MoveUtils.getSpeedEffect())
				+ (double) MoveUtils.getSpeedEffect() / 15;
		double firstvalue = 0.4145 + (double) MoveUtils.getSpeedEffect() / 12.5;
		double decr = (((double) stage / 500) * 2);

		if (stage == 0) {
			// JUMP
			if (timer.delay(300)) {
				timer.reset();
				// Wrapper.INSTANCE.mc().timer.timerSpeed = 1.354f;
			}

			if (!lastCheck.delay(500)) {
				if (!shouldslow) {
					shouldslow = true;
				}
			} else {
				if (shouldslow) {
					shouldslow = false;
				}
			}

			value = 0.64 + (MoveUtils.getSpeedEffect() + (0.028 * MoveUtils.getSpeedEffect())) * 0.134;
		} else if (stage == 1) {
			/*
			 * if (Wrapper.INSTANCE.mc().timer.timerSpeed == 1.354f) { //Wrapper.INSTANCE.mc().timer.timerSpeed = 1.254f; }
			 */

			value = firstvalue;
		} else if (stage >= 2) {
			/*
			 * if (Wrapper.INSTANCE.mc().timer.timerSpeed == 1.254f) { //Wrapper.INSTANCE.mc().timer.timerSpeed = 1f; }
			 */

			value = firstvalue - decr;
		}

		if (shouldslow || !lastCheck.delay(500) || collided) {
			value = 0.2;

			if (stage == 0) {
				value = 0;
			}
		}

		return Math.max(value, shouldslow ? value : MoveUtils.defaultSpeed() + (0.028 * MoveUtils.getSpeedEffect()));
	}

	private void setMotion(double speed) {
		double forward = Wrapper.INSTANCE.player().movementInput.moveForward;
		double strafe = Wrapper.INSTANCE.player().movementInput.moveStrafe;
		float yaw = Wrapper.INSTANCE.player().rotationYaw;

		if ((forward == 0.0D) && (strafe == 0.0D)) {
			Wrapper.INSTANCE.player().motionX = 0;
			Wrapper.INSTANCE.player().motionZ = 0;
		} else {
			if (forward != 0.0D) {
				if (strafe > 0.0D) {
					yaw += (forward > 0.0D ? -45 : 45);
				} else if (strafe < 0.0D) {
					yaw += (forward > 0.0D ? 45 : -45);
				}

				strafe = 0.0D;

				if (forward > 0.0D) {
					forward = 1;
				} else if (forward < 0.0D) {
					forward = -1;
				}
			}
			Wrapper.INSTANCE.player().motionX = forward * speed * Math.cos(Math.toRadians(yaw + 90.0F))
					+ strafe * speed * Math.sin(Math.toRadians(yaw + 90.0F));
			Wrapper.INSTANCE.player().motionZ = forward * speed * Math.sin(Math.toRadians(yaw + 90.0F))
					- strafe * speed * Math.cos(Math.toRadians(yaw + 90.0F));
		
		
		}
		
		
	}
	private double getAACSpeed(int stage, int jumps)
    {
        double value = 0.29;
        double firstvalue = 0.3019;
        double thirdvalue = 0.0286 - (double) stage / 1000;

        if (stage == 0)
        {
            //JUMP
            value = 0.497;

            if (jumps >= 2)
            {
                value += 0.1069;
            }

            if (jumps >= 3)
            {
                value += 0.046;
            }

            Block block = MoveUtils.getBlockUnderPlayer(Wrapper.INSTANCE.player(), 0.01);

            if (block instanceof BlockIce || block instanceof BlockPackedIce)
            {
                value = 0.59;
            }
        }
        else if (stage == 1)
        {
            value = 0.3031;

            if (jumps >= 2)
            {
                value += 0.0642;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 2)
        {
            value = 0.302;

            if (jumps >= 2)
            {
                value += 0.0629;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 3)
        {
            value = firstvalue;

            if (jumps >= 2)
            {
                value += 0.0607;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 4)
        {
            value = firstvalue;

            if (jumps >= 2)
            {
                value += 0.04584;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 5)
        {
            value = firstvalue;

            if (jumps >= 2)
            {
                value += 0.04561;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 6)
        {
            value = firstvalue;

            if (jumps >= 2)
            {
                value += 0.0539;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 7)
        {
            value = firstvalue;

            if (jumps >= 2)
            {
                value += 0.0517;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 8)
        {
            value = firstvalue;

            if (MoveUtils.isOnGround(0.05))
            {
                value -= 0.002;
            }

            if (jumps >= 2)
            {
                value += 0.0496;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 9)
        {
            value = firstvalue;

            if (jumps >= 2)
            {
                value += 0.0475;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 10)
        {
            value = firstvalue;

            if (jumps >= 2)
            {
                value += 0.0455;
            }

            if (jumps >= 3)
            {
                value += thirdvalue;
            }
        }
        else if (stage == 11)
        {
            value = 0.3;

            if (jumps >= 2)
            {
                value += 0.045;
            }

            if (jumps >= 3)
            {
                value += 0.018;
            }
        }
        else if (stage == 12)
        {
            value = 0.301;

            if (jumps <= 2)
            {
                aacCount = 0;
            }

            if (jumps >= 2)
            {
                value += 0.042;
            }

            if (jumps >= 3)
            {
                value += thirdvalue + 0.001;
            }
        }
        else if (stage == 13)
        {
            value = 0.298;

            if (jumps >= 2)
            {
                value += 0.042;
            }

            if (jumps >= 3)
            {
                value += thirdvalue + 0.001;
            }
        }
        else if (stage == 14)
        {
            value = 0.297;

            if (jumps >= 2)
            {
                value += 0.042;
            }

            if (jumps >= 3)
            {
                value += thirdvalue + 0.001;
            }
        }

        if (Wrapper.INSTANCE.player().moveForward <= 0)
        {
            value -= 0.06;
        }

        if (Wrapper.INSTANCE.player().collidedHorizontally)
        {
            value -= 0.1;
            aacCount = 0;
        }

        return value;
    }

    private void setTickLength(float tickLength)
    {
        try
        {
            Field fTimer = Minecraft.getMinecraft().getClass().getDeclaredField(Mapping.timer);
            fTimer.setAccessible(true);

            Field fTickLength = net.minecraft.util.Timer.class.getDeclaredField(Mapping.tickLength);
            fTickLength.setAccessible(true);
            fTickLength.setFloat(fTimer.get(Minecraft.getMinecraft()), tickLength);

        }catch(ReflectiveOperationException e)
        {
            throw new RuntimeException(e);
        }
    }





}
